package org.medusa.sample;

import org.medusa.core.EventCallback;
import org.medusa.core.EventPump;
import org.medusa.log.ILog;
import org.medusa.network.tcp.TcpAsyncBinaryConnector;

//import com.lumingame.common.def.MsgCode;

//1. runtime.Gosched();
//2. Packet ByteArray
//3.evp由AsyncConnector管理还是自管理 却取决于tcpconn构造时的evp对象是否为空
//4.release()重入问题

public abstract class AsyncConnector extends TcpAsyncBinaryConnector<Packet> {

	private Packet half_packet_recv = null;
	private Packet pack_idle = null;
	private AsyncConnector self = null;
	private long ping_ms_value = 0;

	public AsyncConnector(String name, ILog log, EventPump evp, int rcv_buf,
			int snd_buf, int idle_second) {

		super(name, log, evp, rcv_buf, snd_buf, idle_second);

		this.pack_idle = Packet.NewRequest(/* MsgCode.IN_ECHO */0);
		this.self = this;

		this.AddProtocol(/* MsgCode.IN_ECHO */0, new EventCallback<Packet>() {
			@Override
			public void execute(Packet args) {
				self.Debug("remote is alive!");
			}

			@Override
			public void removed() {
				// TODO Auto-generated method stub
				
			}

		});
	}

	public long Ping() {
		return this.ping_ms_value;
	}

	@Override
	protected void event_callback_Idle() {
		this.SendPacket(this.pack_idle);
		this.Error("sent idle packet!");
	}

	@Override
	protected void event_callback_pre_sent(Packet pack) {
		if (pack != null)
			if (pack.IsRequest())
				pack.SetTimeStamp();
	}

	@Override
	protected Packet parse_packet() {
		Packet pack = null;
		if (this.half_packet_recv == null) {

			if (this.ringbuf.DataSize() >= Packet.PACKET_HEAD_LEN) {
				byte m = this.ringbuf.ReadInt8(); // 1 // byte //1:+ |2:- |3:*
													// |4/
				short a = this.ringbuf.ReadInt16LE(); // 3 // A, B int16
				short b = this.ringbuf.ReadInt16LE(); // 5
				short c = this.ringbuf.ReadInt16LE();// 7
				int len = this.ringbuf.ReadInt32LE();// 11
				short des = this.ringbuf.ReadInt16LE();// 13

				int uuid = this.ringbuf.ReadInt32LE();// 17
				boolean is_space_msg = this.ringbuf.ReadInt8() != 0;// 18
				int except_uuid = this.ringbuf.ReadInt32LE();// 22
				int notify_or_result = this.ringbuf.ReadInt32LE();// 26
				long timestamp = this.ringbuf.ReadInt64LE();// 27

				pack = new Packet(m, a, b, c, len, des, uuid, is_space_msg,
						except_uuid, notify_or_result, timestamp);
				// pack.Show("recved:");
				if (this.ringbuf.DataSize() >= (pack.PacketSize() - Packet.PACKET_HEAD_LEN)) {
					pack.WriteBytes(this.ringbuf,
							(pack.PacketSize() - Packet.PACKET_HEAD_LEN));
					// pack.Show("Connector--PacketReceived");
				} else {
					this.half_packet_recv = pack;
					pack.WriteBytes(this.ringbuf, this.ringbuf.DataSize());
					pack = null;
				}
			}// end : if (this.ringbuf.DataLen() >= Packet.PACKET_HEAD_LEN)

		} else {

			pack = this.half_packet_recv;
			int residual = pack.PacketSize() - pack.DataSize();

			if (this.ringbuf.DataSize() >= residual) {
				pack.WriteBytes(this.ringbuf, residual);
				this.half_packet_recv = null;
				// pack.Show("Acceptor--PacketReceived")
			} else {
				pack.WriteBytes(this.ringbuf, this.ringbuf.DataSize());
				pack = null;
			}
		}// end of :if (this.half_packet_recv == null)...else...

		if (pack != null) {
			if (pack.IsResponse())
				this.ping_ms_value = System.currentTimeMillis()
						- pack.TimeStamp();
		}
		return pack;
	}

}
